/**
 * 
 */
package research.sbookmarking.output;

import java.util.*;
import java.io.*;

import org.afox.util.RMethod;
import org.apache.poi.hssf.usermodel.*;
import org.connotea.Post;

import research.sbookmarking.*;
import research.sbookmarking.input.InputController;
import research.sbookmarking.process.ProcessController;
import research.sbookmarking.process.util.*;

/**
 * @author <a href="mailto:aatleung@gmail.com">Albert Leung</a>
 * @version 1.0
 */

public class OutputController {

	private TreeMap<String,OutputStreamFactory> factoryMap = new TreeMap<String,OutputStreamFactory>();
	
	private static OutputController anInstance = null;
	
	/**
	 * 
	 */
	private OutputController() {
		factoryMap.put("OutputStream",OutputStreamFactory.getInstance());
		factoryMap.put("DataOutputStream", DataOutputStreamFactory.getInstance());
		factoryMap.put("ObjectOutputStream",ObjectOutputStreamFactory.getInstance());
		//factoryMap.put("pipedstream",PipedStreamFactory.getInstance());
	}

	private void writeBookmarkUserTag(HSSFWorkbook wb, TreeMap<String,Object> data)  {
		ArrayList<Object> tmp = new ArrayList<Object>();
		HSSFSheet sheet = wb.createSheet("URL-User-Tag");
		this.setupExcelFile(sheet, tmp, 0);
		tmp.clear();
		tmp.add(String.valueOf("This table describes when a URL was bookmarked, by whom, the tags used and number " +
				"of tags used to describe the URL."));
		setupExcelFile(sheet, tmp,1);
		tmp.clear();
		tmp.add(String.valueOf("NB: This data is from the post retrieved and there may be more user who have bookmarked the links shown."));
		setupExcelFile(sheet, tmp,2);
		tmp.clear();
		String[] header = {"UID", "URL", "user", "tag (subject)", "frequency"};
		AppController.getInstance().copy(tmp,Arrays.asList(header).iterator());
		setupExcelFile(sheet, tmp,3);
		this.saveExcelFile(wb, sheet, 4, data);
		sheet.createFreezePane( 0, 4, 0, 4 );
	}
 
	private void writeUrl(HSSFWorkbook wb, String label, TreeMap<String,Object> data)  {
		ArrayList<Object> tmp = new ArrayList<Object>();
		HSSFSheet sheet = wb.createSheet("URL-"+label);
		this.setupExcelFile(sheet, tmp, 0);
		tmp.clear();
		tmp.add(String.valueOf("This table describes the "+label+" used for each URL used and number of "+label+" used."));
		setupExcelFile(sheet, tmp,1);
		tmp.clear();
		tmp.add(String.valueOf("NB: This data is from the posts retrieved and the distribution may be high than shown here."));
		setupExcelFile(sheet, tmp,2);
		tmp.clear();
		String[] header = {"URL", label, "frequency"};
		AppController.getInstance().copy(tmp,Arrays.asList(header).iterator());
		setupExcelFile(sheet, tmp,3);
		this.saveExcelFile(sheet, (short)4, data);
		sheet.createFreezePane( 0, 4, 0, 4 );
	}
 
	private void writeUserTag(HSSFWorkbook wb, String label, TreeMap<String,Object> data)  {
		ArrayList<Object> tmp = new ArrayList<Object>();
		HSSFSheet sheet = wb.createSheet("User-Tag");
		this.setupExcelFile(sheet, tmp, 0);
		tmp.clear();
		tmp.add(String.valueOf("This table describes the tags each user used and its distribution."));
		setupExcelFile(sheet, tmp,1);
		tmp.clear();
		tmp.add(String.valueOf("NB: This data is from the posts retrieved and the distribution may be high than shown here."));
		setupExcelFile(sheet, tmp,2);
		tmp.clear();
		String[] header = {"user", label, "frequency"};
		AppController.getInstance().copy(tmp,Arrays.asList(header).iterator());
		setupExcelFile(sheet, tmp,3);
		
		if (label.equals("Unique Tags")){
			this.saveExcelFile(sheet, (short)4, data);
		}
		else{
			this.saveExcelFile(sheet, (long)4, data);
		}
		
		sheet.createFreezePane( 0, 4, 0, 4 );
	}
 
/*
	private void writeBookmark(HSSFWorkbook wb, List<String> data)  {
		ArrayList<Object> tmp = new ArrayList<Object>();
		
		HSSFSheet sheet = wb.createSheet("URL");
		this.setupExcelFile(sheet, tmp, 0);
		tmp.clear();
		tmp.add(String.valueOf("This table describes the freq a URL was bookmarked, no. of user/url, the no. of tags/url, " +
				"the no. of unique tags/url."));
		setupExcelFile(sheet, tmp,1);
		tmp.clear();
		String[] header = {"URL", "No of user/url", "No. of unique tags/url", "Total no. of tags/url"};
		AppController.getInstance().copy(tmp,Arrays.asList(header).iterator());
		setupExcelFile(sheet, tmp,2);
		this.saveExcelFile(sheet, 3, data);
		sheet.createFreezePane( 0, 3, 0, 3 );
	}
 
	private void writeUser(HSSFWorkbook wb, List<String> data)  {
		ArrayList<Object> tmp = new ArrayList<Object>();
		HSSFSheet sheet = wb.createSheet("User");
		this.setupExcelFile(sheet, tmp, 0);
		tmp.clear();
		tmp.add(String.valueOf("This table describes the freq a users who bookmarked, total no of tags/user."));
		setupExcelFile(sheet, tmp,1);
		tmp.clear();
		String[] header = {"User", "No of posting/user", "Unique no. of tags/user", "Total no. tags/url"};
		AppController.getInstance().copy(tmp,Arrays.asList(header).iterator());
		setupExcelFile(sheet, tmp,2);
		this.saveExcelFile(sheet, 3, data);
		sheet.createFreezePane( 0, 3, 0, 3 );
	}
*/
	
	private void writeTag(HSSFWorkbook wb, TreeMap<String,Object> data)  {
		ArrayList<Object> tmp = new ArrayList<Object>();
		//tmp.add(timeline);
		HSSFSheet sheet = wb.createSheet("Tag");
		this.setupExcelFile(sheet, tmp, 0);
		tmp.clear();
		tmp.add(String.valueOf("This table describes the freq a users who bookmarked, total no of tags/user."));
		setupExcelFile(sheet, tmp,1);
		tmp.clear();
		String[] header = {"Tag", "Frequency"};
		AppController.getInstance().copy(tmp,Arrays.asList(header).iterator());
		setupExcelFile(sheet, tmp,2);
		this.saveExcelFile(sheet, (short)3, data);
		sheet.createFreezePane( 0, 3, 0, 3 );
	}

	private void writeUser(HSSFWorkbook wb, TreeMap<String,Object> data)  {
		ArrayList<Object> tmp = new ArrayList<Object>();
		//tmp.add(timeline);
		HSSFSheet sheet = wb.createSheet("User");
		this.setupExcelFile(sheet, tmp, 0);
		tmp.clear();
		tmp.add(String.valueOf("This table describes the total no of posting/user."));
		setupExcelFile(sheet, tmp,1);
		tmp.clear();
		String[] header = {"User", "Frequency"};
		AppController.getInstance().copy(tmp,Arrays.asList(header).iterator());
		setupExcelFile(sheet, tmp,2);
		this.saveExcelFile(sheet, (short)3, data);
		sheet.createFreezePane( 0, 3, 0, 3 );
	}

	private void writeTime (HSSFWorkbook wb, String label, TreeMap<String,Object> data){
		ArrayList<Object> tmp = new ArrayList<Object>();
		//tmp.add(timeline);
		HSSFSheet sheet = wb.createSheet(label+"-Time");
		this.setupExcelFile(sheet, tmp, 0);
		tmp.clear();
		tmp.add(String.valueOf("This table describes the time difference between each posting from the perspective of " + label));
		setupExcelFile(sheet, tmp,1);
		tmp.clear();
		String[] header = {label, "Date (DD-MM-YYYY GMT)","Time Elapsed (days)"};
		AppController.getInstance().copy(tmp,Arrays.asList(header).iterator());
		setupExcelFile(sheet, tmp,2);
		this.saveExcel(sheet, (short)3, data);
		sheet.createFreezePane( 0, 3, 0, 3 );
	}

	private OutputStreamFactory getFactory(String factoryName){
		if (factoryMap.containsKey(factoryName)){
			return (OutputStreamFactory)factoryMap.get(factoryName);
		}
		throw new RuntimeException ("There is no " + factoryName + "Factory.");
	}
	
	public PrintWriter getWriterStream (String filename, String factoryName, boolean append) {
		
		OutputStreamFactory factory = getFactory(factoryName);
		if (factory==null) {
			factory = (OutputStreamFactory)RMethod.invokeClassMethod("research.sbookmarking.output"+ 
					factoryName+"Factory", "getInstance", new ArrayList<Object>());
			factoryMap.put(factoryName, factory);
		}
		PrintWriter stream = factory.getFileWriter(filename,append);
		factory.addStream(filename, stream);
		return stream;
	}

	private OutputStream getOutputStream (String filename, String factoryName, boolean append) {
		OutputStreamFactory factory = getFactory(factoryName);
		if (factory==null) {
			factory = (OutputStreamFactory)RMethod.invokeClassMethod("research.sbookmarking.output"+ 
					factoryName+"Factory", "getInstance", new ArrayList<Object>());
			factoryMap.put(factoryName, factory);
		}
		OutputStream stream = factory.getOutputStream(filename,append);
		factory.addStream(filename, stream);
		return stream;
	}
	
	/**
	 * 
	 * @return OutputController
	 */
	public static OutputController getInstance() {
		if (anInstance==null) {
			anInstance = new OutputController();
		}
		
		return anInstance;
	}
	
	public void saveRawData (String filename, List<Post> temp, boolean append){
		try {
			PrintWriter file = getWriterStream(filename,"DataOutputStream", append);
			Iterator<Post> results = temp.iterator();
			
			while (results.hasNext()) {
				file.println(results.next());
			}
			file.flush();
		}
		catch (RuntimeException e){
			System.err.println ("Error in " + e.getClass().getName() + ": ");
			System.err.println (e.getCause());
			e.printStackTrace(System.err);
		}
	}

	public void writeDsvDataHeader (String filename, Object notes, String header){
		try {
			PrintWriter file = getWriterStream(filename,"DataOutputStream", false);
			
			file.println(notes);
			file.println(header);
			file.flush();
		}
		catch (RuntimeException e){
			System.err.println ("Error in " + e.getClass().getName() + ": ");
			System.err.println (e.getCause());
			e.printStackTrace(System.err);
		}
	}
	
	public void saveDsvData (String filename, List<Post> results, boolean append){
		try {
			java.text.SimpleDateFormat format = new java.text.SimpleDateFormat ("dd/MM/yyyy H:mm");
			TimeZone gstTime = TimeZone.getTimeZone("GMT"); 
			format.setTimeZone(gstTime);
			PrintWriter file = getWriterStream(filename,"DataOutputStream", append);
			
			for (int i=0; i < results.size(); i++){
				Post result = results.get(i);
				
				file.println(format.format(result.getCreated()) + "\t" + 
					result.getBookmark().getLink().toString() + "\t" +
					result.getCreator() +"\t" +
					//result.getTitle() + "\t" +
					//result.getDescription() + "\t" +
					"\"" + StringUtils.convertList(result.getSubjects().iterator()) + "\" \t" +
					result.isMyWork() + "\t" +
					isCitation(result)  + "\t" +
					format.format(result.getUpdated()));
			}
			
			file.flush();
		}
		catch (RuntimeException e){
			System.err.println ("Error in " + e.getClass().getName() + ": ");
			System.err.println (e.getCause());
			e.printStackTrace(System.err);
		}
	}
	
	public List<String> saveQuery (String factory, String filename) throws IOException{
		InputController ic = InputController.getInstance();
		ProcessController pc = ProcessController.getInstance();
		
		List<String> filenames = ic.readQueryList(filename,factory);
		ArrayList<Object> param = new ArrayList<Object>(3);
		TreeMap<String,Object> treeMap = new TreeMap<String,Object> ();
		HSSFWorkbook wb = null;
		String ext = null;
		int uid = 1;

		if (filename.equals(filename.replaceAll(".txt.gz", ".xls"))){
			ext=filename.replaceAll(".txt", ".xls");
		}
		else {
			ext=filename.replaceAll(".txt.gz", ".xls");
		}

		System.out.println("Calculating URL-User-Tag....");
		int i=0;
		for (i=0; i<filenames.size();i++){
			System.out.println("Retrieving data from "+filenames.get(i));
			param.add(ic.getInputStream(filenames.get(i), "ObjectInputStream"));
			param.add(Integer.valueOf(uid));
			param.add(treeMap);
			uid = ((Integer)pc.processData("calcURLUserTag",param)).intValue();
			ic.closeStream("ObjectInputStream", filenames.get(i));
			param.clear();
			
			if (i%50==0){
				wb = new HSSFWorkbook();
				writeBookmarkUserTag(wb, treeMap);
				String fileName = "data/xls/URL-User-Tag-" + i/50 + "-"+ ext;
				saveToExcel(fileName, wb);
				treeMap.clear();
			}
		}

		if (i%50==0||i%50>1){
			wb = new HSSFWorkbook();
			writeBookmarkUserTag(wb, treeMap);
			String fileName = "data/xls/URL-User-Tag-" + (i/50+1) + "-"+ ext;
			saveToExcel(fileName, wb);
		}
		treeMap.clear();

		System.out.println("Calculating Tag....");
		for (i=0; i<filenames.size();i++){
			System.out.println("Retrieving data from "+filenames.get(i));
			param.add(ic.getInputStream(filenames.get(i), "ObjectInputStream"));
			param.add(treeMap);
			pc.processData("calcTags",param);
			//AppController.getInstance().copy("copy",TreeMap, new ArrayList(tempTreeMap.keySet()), 
			//		new ArrayList(tempTreeMap.values()));
			ic.closeStream("ObjectInputStream", filenames.get(i));
			param.clear();
			
/*			if (i%50==0){
				wb = new HSSFWorkbook();
				writeTag(wb, TreeMap);
				fileName = "data/xls/Tags-" + filename.replaceAll(".txt.gz", ".xls");
				saveToExcel(fileName, wb);
				TreeMap.clear();
			}
*/		}
		
		wb = new HSSFWorkbook();
		writeTag(wb, treeMap);
		filename = "data/xls/Tags-" + ext;
		saveToExcel(filename, wb);
		treeMap.clear();

		System.out.println("Calculating User....");
		for (i=0; i<filenames.size();i++){
			System.out.println("Retrieving data from "+filenames.get(i));
			param.add(ic.getInputStream(filenames.get(i), "ObjectInputStream"));
			param.add(treeMap);
			pc.processData("calcUser",param);
			//AppController.getInstance().copy("copy",TreeMap, new ArrayList(tempTreeMap.keySet()), 
			//		new ArrayList(tempTreeMap.values()));
			ic.closeStream("ObjectInputStream", filenames.get(i));
			param.clear();
			
/*			if (i%50==0){
				wb = new HSSFWorkbook();
				writeTag(wb, TreeMap);
				fileName = "data/xls/Tags-" + filename.replaceAll(".txt.gz", ".xls");
				saveToExcel(fileName, wb);
				TreeMap.clear();
			}
*/		}
		
		wb = new HSSFWorkbook();
		writeUser(wb, treeMap);
		filename = "data/xls/User-" + ext;
		saveToExcel(filename, wb);
		treeMap.clear();
		System.gc();
		
/*
		TreeMap.clear();
		System.out.println("Calculating Tag....");
		for (int i=0; i<filenames.size();i++){
			param.add(ic.getInputStream(filenames.get(i), "ObjectInputStream"));
			param.add(TreeMap);
			pc.processData("calcTags",param);
			//AppController.getInstance().copy("copy",TreeMap, new ArrayList(tempTreeMap.keySet()), 
			//		new ArrayList(tempTreeMap.values()));
			ic.closeStream("ObjectInputStream", filenames.get(i));
			param.clear();
		}
		
		wb = new HSSFWorkbook();
		writeTag(wb, TreeMap);
		fileName = "data/xls/Tags-" + filename.replaceAll(".txt.gz", ".xls");
		saveToExcel(fileName, wb);
		TreeMap.clear();
		System.out.println("Calculating Tag....");
		for (int i=0; i<filenames.size();i++){
			param.add(ic.getInputStream(filenames.get(i), "ObjectInputStream"));
			param.add(TreeMap);
			pc.processData("calcTags",param);
			//AppController.getInstance().copy("copy",TreeMap, new ArrayList(tempTreeMap.keySet()), 
			//		new ArrayList(tempTreeMap.values()));
			ic.closeStream("ObjectInputStream", filenames.get(i));
			param.clear();
		}
		
		wb = new HSSFWorkbook();
		writeTag(wb, TreeMap);
		fileName = "data/xls/-" + filename.replaceAll(".txt.gz", ".xls");
		saveToExcel(fileName, wb);

/*
		writeBookmark(wb, container.getURL());
		writeUser(wb, container.getUniqueUsers());
		writeTag(wb, container.getTags());
		filename = "data/Freqs(URL User Tag)-" + fileName;
		saveToExcel(filename, wb);
		
		Post test = new Post();
		test.getSubjects();
*/
		return filenames;
	}
	
	public void outputURLUniqueTag (List<String>filenames) throws IOException{
		System.out.println("Calculating URL-Unique Tag....");
		InputController ic = InputController.getInstance();
		ProcessController pc = ProcessController.getInstance();
		ArrayList<Object> param = new ArrayList<Object>(1);
		TreeMap <String,Object>treeMap = new TreeMap<String,Object>();
		String filename = filenames.get(0);
		String ext = filename.substring(filename.lastIndexOf("/"),filename.indexOf("2008"))+".xls";
		ext = StringUtils.convertIllegalChar(ext);

		int i=0;
		for (i=0; i<filenames.size();i++){
			System.out.println("Retrieving data from "+filenames.get(i));
			param.add(ic.getInputStream(filenames.get(i), "ObjectInputStream"));
			param.add("getSubjects");
			param.add(treeMap);
			pc.processData("calcURLUnique",param);
			//TreeMap tempTreeMap = (TreeMap)pc.processData("calcURLUnique",param);
			//AppController.getInstance().copy("copyUnique",TreeMap, new ArrayList(tempTreeMap.keySet()), 
			//		new ArrayList(tempTreeMap.values()));
			ic.closeStream("ObjectInputStream", filenames.get(i));
			param.clear();

			if (i%50==0){
				HSSFWorkbook wb = new HSSFWorkbook();
				writeUrl(wb, "Unique Tags", treeMap);
				filename = "data/xls/URL-Unique Tags-" + i/50 + "-" + ext;
				saveToExcel(filename, wb);
				treeMap.clear();
			}
		}
		
		if (i%50==0 || i%50>1){
			HSSFWorkbook wb = new HSSFWorkbook();
			writeUrl(wb, "Unique Tags", treeMap);
			filename = "data/xls/URL-Unique Tags-" + (i/50+1) + "-" + ext;
			saveToExcel(filename, wb);
			treeMap.clear();
		}
	}

	public void outputURLTag (ArrayList<String> filenames) throws IOException{
		System.out.println("Calculating URL-Tag....");
		InputController ic = InputController.getInstance();
		ProcessController pc = ProcessController.getInstance();
		ArrayList<Object> param = new ArrayList<Object>(1);
		TreeMap <String,Object>treeMap = new TreeMap<String,Object>();
		String filename = filenames.get(0);
		String ext = filename.substring(filename.lastIndexOf("/"),filename.indexOf("2008"))+".xls";
		ext = StringUtils.convertIllegalChar(ext);

		int i=0;
		for (i=0; i<filenames.size();i++){
			System.out.println("Retrieving data from "+filenames.get(i));
			param.add(ic.getInputStream(filenames.get(i), "ObjectInputStream"));
			param.add("getSubjects");
			param.add(treeMap);
			pc.processData("calcURL",param);
			ic.closeStream("ObjectInputStream", filenames.get(i));
			param.clear();

			if (i%50==0){
				HSSFWorkbook wb = new HSSFWorkbook();
				writeUrl(wb, "Tags", treeMap);
				filename = "data/xls/URL-Tags-" + i/50 + "-" + ext;
				saveToExcel(filename, wb);
				treeMap.clear();
			}

		}
		
		if (i%50==0 || i%50>1){
			HSSFWorkbook wb = new HSSFWorkbook();
			writeUrl(wb, "Tags", treeMap);
			filename = "data/xls/URL-Tags-" + (i/50+1) + ext;
			saveToExcel(filename, wb);
			treeMap.clear();
		}
	}
	
	public void outputURLUser (ArrayList<String> filenames) throws IOException{
		System.out.println("Calculating URL-User ....");
		InputController ic = InputController.getInstance();
		ProcessController pc = ProcessController.getInstance();
		ArrayList<Object> param = new ArrayList<Object>(1);
		TreeMap <String,Object>treeMap = new TreeMap<String,Object>();
		String filename = filenames.get(0);
		String ext = filename.substring(filename.lastIndexOf("/"),filename.indexOf("2008"))+".xls";
		ext = StringUtils.convertIllegalChar(ext);

		int i=0;
		for (i=0; i<filenames.size();i++){
			System.out.println("Retrieving data from "+filenames.get(i));
			param.add(ic.getInputStream(filenames.get(i), "ObjectInputStream"));
			param.add("getCreator");
			param.add(treeMap);
			pc.processData("calcURL",param);
			//AppController.getInstance().copy("copy",TreeMap, new ArrayList(tempTreeMap.keySet()), 
			//		new ArrayList(tempTreeMap.values()));
			ic.closeStream("ObjectInputStream", filenames.get(i));
			param.clear();

			if (i%50==0){
				HSSFWorkbook wb = new HSSFWorkbook();
				writeUrl(wb, "User", treeMap);
				filename = "data/xls/URL-User-" + i/50+ "-" + ext;
				saveToExcel(filename, wb);
				treeMap.clear();
			}
		}
		
		if (i%50==0 || i%50>1){
			HSSFWorkbook wb = new HSSFWorkbook();
			writeUrl(wb, "User", treeMap);
			filename = "data/xls/URL-User-" + (i/50+1) + "-" + ext;
			saveToExcel(filename, wb);
			treeMap.clear();
		}
	}
	
	public void outputUserUniqueTag (ArrayList<String> filenames) throws IOException{
		System.out.println("Calculating User-Unque Tag....");
		InputController ic = InputController.getInstance();
		ProcessController pc = ProcessController.getInstance();
		ArrayList<Object> param = new ArrayList<Object>(1);
		TreeMap <String,Object>treeMap = new TreeMap<String,Object>();
		String filename = filenames.get(0);
		String ext = filename.substring(filename.lastIndexOf("/"),filename.indexOf("2008"))+".xls";
		ext = StringUtils.convertIllegalChar(ext);

		int i=0;
		for (i=0; i<filenames.size();i++){
			System.out.println("Retrieving data from "+filenames.get(i));
			param.add(ic.getInputStream(filenames.get(i), "ObjectInputStream"));
			param.add(treeMap);
			pc.processData("calcUserUniqueTags",param);
			//AppController.getInstance().copy("copyUnique",TreeMap, new ArrayList(tempTreeMap.keySet()), 
			//		new ArrayList(tempTreeMap.values()));
			ic.closeStream("ObjectInputStream", filenames.get(i));
			param.clear();

			if (i%50==0){
				HSSFWorkbook wb = new HSSFWorkbook();
				writeUserTag(wb, "Unique Tags", treeMap);
				filename = "data/xls/User-Unique Tags-" + i/50 + "-"+ ext;
				saveToExcel(filename, wb);
				treeMap.clear();
			}
		}
		
		if (i%50==0||i%50>1){
			HSSFWorkbook wb = new HSSFWorkbook();
			writeUserTag(wb, "Unique Tags", treeMap);
			filename = "data/xls/User-Unique Tags-" + (i/50+1) + "-"+ ext;
			saveToExcel(filename, wb);
		}
	}

	public void outputUserTag (ArrayList<String> filenames) throws IOException{
		InputController ic = InputController.getInstance();
		ProcessController pc = ProcessController.getInstance();
		ArrayList<Object> param = new ArrayList<Object>(1);
		TreeMap <String,Object>treeMap = new TreeMap<String,Object>();
		String filename = filenames.get(0);
		String ext = filename.substring(filename.lastIndexOf("/"),filename.indexOf("2008"))+".xls";
		ext = StringUtils.convertIllegalChar(ext);

		int i=0;
		for (i=0; i<filenames.size();i++){
			System.out.println("Retrieving data from "+filenames.get(i));
			param.add(ic.getInputStream(filenames.get(i), "ObjectInputStream"));
			param.add(treeMap);
			pc.processData("calcUserTags",param);
			//AppController.getInstance().copy("copy",TreeMap, new ArrayList(tempTreeMap.keySet()), 
			//		new ArrayList(tempTreeMap.values()));
			ic.closeStream("ObjectInputStream", filenames.get(i));
			param.clear();

			if (i%50==0){
				HSSFWorkbook wb = new HSSFWorkbook();
				writeUserTag(wb, "Tags", treeMap);
				filename = "data/xls/User-Tags-" + i/50 + "-"+ ext;
				saveToExcel(filename, wb);
				treeMap.clear();
			}
		}

		if (i%50==0 || i%50>1){
			HSSFWorkbook wb = new HSSFWorkbook();
			writeUserTag(wb, "Tags", treeMap);
			filename = "data/xls/User-Tags-" + (i/50+1) + "-"+ ext;
			saveToExcel(filename, wb);
		}

	}
	
	public void outputTime (ArrayList<String> filenames, String query) throws IOException{
		InputController ic = InputController.getInstance();
		ProcessController pc = ProcessController.getInstance();
		ArrayList<Object> param = new ArrayList<Object>(1);
		TreeMap <String,Object>treeMap = new TreeMap<String,Object>();
		String filename = filenames.get(0);
		String ext = filename.substring(filename.lastIndexOf("/"),filename.indexOf("2008"))+".xls";
		ext = StringUtils.convertIllegalChar(ext);

		int i=0;
		for (i=0; i<filenames.size();i++){
			System.out.println("Retrieving data from "+filenames.get(i));
			param.add(ic.getInputStream(filenames.get(i), "ObjectInputStream"));
			param.add(query);
			param.add(treeMap);
			pc.processData("calcTime",param);
			ic.closeStream("ObjectInputStream", filenames.get(i));
			param.clear();

			if (i%50==0){
				HSSFWorkbook wb = new HSSFWorkbook();
				writeTime(wb, query, treeMap);
				filename = "data/xls/" + query + "-Time-" +i/50 + "-"+ext;
				saveToExcel(filename, wb);
				treeMap.clear();
			}
		}

		if (i%50==0 || i%50>1){
			HSSFWorkbook wb = new HSSFWorkbook();
			writeTime(wb, query, treeMap);
			filename = "data/xls/" + query + "-Time-" + (i/50+1) + "-"+ ext;
			saveToExcel(filename, wb);
		}
	}
	
	public void saveObjectData (String filename, Object data, boolean append){
		try {
			//ObjectOutputStreamFactory factory = (ObjectOutputStreamFactory)getFactory("objectoutputstream");
			ObjectOutputStream file = (ObjectOutputStream)getOutputStream(filename,"ObjectOutputStream",append); 
			file.writeObject(data);

			file.flush();
		}
		catch (IOException e){
			System.err.println ("Error in " + e.getClass().getName() + ": ");
			System.err.println (e.getCause());
			e.printStackTrace(System.err);
		}
	}
	
	public void createXmlQuery(String filename, String queryName, String name, Iterator<String> queryList, boolean append) {
		PrintWriter file = getWriterStream(filename,"DataOutputStreamFactory",append);
			
		file.println ("<Setting>");
		file.println ("\t<Command classpath=\"research.sbookmarking.input.\" class=\"BookmarkCommand\">");
		file.println ("\t\t<Param name=\"container\" value=\"GeneralContainer\"/>");
		file.println ("\t\t<Param name=\"queryName\" value=\""+queryName+"\"/>");
		file.println ("\t\t<List>");

		while (queryList.hasNext()) {
			file.println ("\t\t\t<CParam name=\""+name+"\" value=\""+ queryList.next() +"\"/>");
		}

		file.println ("\t\t</List>");
		file.println ("\t</Command>");
		file.println ("</Setting>");
		file.flush();
		file.close();
	}

	public void saveQuery (String filename, String factory, String query, boolean append){
		PrintWriter file = getWriterStream(filename,factory,append);
		saveQuery(file, query);
	}
	
	private void saveQuery (PrintWriter file, String query){
		file.println (query);
		file.flush();
	}
	
	public void saveQuery (String filename, String factory, List<String> query, boolean append){
		PrintWriter file = getWriterStream(filename,factory,append);
		Iterator<String> queries = query.iterator();
		while (queries.hasNext()){
			saveQuery(file, queries.next());
		}
		file.close();
	}
	
	public void closeStream(String factory, String filename){
		OutputStreamFactory osf = getFactory(factory);
		Object stream = osf.getStream(filename);
		RMethod.invoke(stream,"close",new ArrayList<Object>());
		osf.removeStream(filename);
	}

	public void setupExcelFile(HSSFSheet sheet, ArrayList<Object> headings, int rowNum){
		this.setCells(sheet, headings, rowNum);
	}

/*
  	private Date convertToGMT (Date date){
 		Date tmp = (Date) date.clone();
		long time = date.getTime()-TimeZone.getDefault().getOffset(date.getTime());
		tmp.setTime(time);
		return tmp;
	}
*/
	
	private boolean isCitation(Post result){
		boolean citation = false;
		
		if (result.getBookmark().getCitation()!=null){
			citation = true;
		}
		
		return citation;
	}

	private void setCells (HSSFSheet sheet, List<Object> output, int rowNum){
		ArrayList<Object> param = new ArrayList<Object>();
		HSSFRow row = sheet.createRow(rowNum);
		
		for(short i=0; i<output.size(); i++){
			if (output.get(i)!=null){
				HSSFCell cell = row.createCell((i));

				param.clear();
				param.add(output.get(i));
				RMethod.invoke(cell, "setCellValue", param);
			}
		}
	}
	
	/**
	 * This methods saves the data into an excel file format.
	 * 
	 * @param filename name of the file to save the data to
	 * @param wb
	 * @throws IOException
	 */
	public void saveToExcel (String filename, HSSFWorkbook wb) throws IOException{
		OutputStream file = getOutputStream(filename,"OutputStream", false);
		wb.write(file);
		file.flush();
		file.close();
		OutputStreamFactory.getInstance().removeStream(filename);
	}
	
	/**
	 * This method is used to bring out URL-User-Tag 
	 * @param wb
	 * @param sheet
	 * @param rowNum
	 * @param data
	 */
	@SuppressWarnings("unchecked")
	public void saveExcelFile(HSSFWorkbook wb, HSSFSheet sheet, int rowNum, TreeMap<String,Object> data){
		List<String> keys = new ArrayList<String>(data.keySet());
		ArrayList<Object> temp = new ArrayList<Object>();
		for (int i=0; i<keys.size();i++){
			TreeMap<String,Object> urlMap = (TreeMap<String,Object>)data.get(keys.get(i));
			for (int j=0;j<urlMap.size();j++){
				List<String> urlKeys = new ArrayList<String>(urlMap.keySet());
				
				TreeMap<String,Object>userMap = (TreeMap<String,Object>)urlMap.get(urlKeys.get(j));
				for (int k=0;k<userMap.size();k++){
					temp.add(keys.get(i));
					temp.add(urlKeys.get(j));
					
					AppController.getInstance().copy(temp, (createOutput (k, userMap)).iterator());
					setCells(sheet,temp, (int)rowNum);
					rowNum++;
					temp.clear();
				}
			}
		}
	}

	@SuppressWarnings("unchecked")
	public void saveExcelFile(HSSFSheet sheet, long rowNum, TreeMap<String,Object> data){
		List<String> keys = new ArrayList<String>(data.keySet());
		ArrayList<Object> temp = new ArrayList<Object>();

		for (int i=0; i<keys.size();i++){
			TreeMap<String,Object> tagTreeMap = (TreeMap<String,Object>)data.get(keys.get(i));
			for (int j=0; j<tagTreeMap.size(); j++){
				temp.add(keys.get(i));
				AppController.getInstance().copy(temp, (createOutput (j, tagTreeMap)).iterator());
				setCells(sheet,temp, (int)rowNum);
				rowNum++;
				temp.clear();
				
			}
		}
	}

	@SuppressWarnings("unchecked")
	private void saveExcel(HSSFSheet sheet, short rowNum, TreeMap<String,Object> data){
		List<String> keys = new ArrayList<String>(data.keySet());
		ArrayList<Object> temp = new ArrayList<Object>();

		java.text.SimpleDateFormat format = new java.text.SimpleDateFormat ("dd/MM/yyyy H:mm");
		TimeZone gstTime = TimeZone.getTimeZone("GMT"); 
		format.setTimeZone(gstTime);
		
		for (int i=0; i<keys.size();i++){
			ArrayList<Date> time = (ArrayList<Date>)data.get(keys.get(i));
			
/*			temp.add(keys.get(i));
			temp.add(time.get(0));
			setCells(sheet,temp, (int)rowNum);
			rowNum++;
			temp.clear();
*/			
			//time.set(0,new Date(0));
			for (int j=0; j<time.size(); j++){
				temp.add(keys.get(i));
				temp.add(format.format(time.get(j)));
				temp.add(Double.valueOf((time.get(j).getTime()-time.get(0).getTime())/86400000.0));
				setCells(sheet,temp, (int)rowNum);
				rowNum++;
				temp.clear();
			}
		}
	}
	
	public void saveExcelFile(HSSFSheet sheet, short rowNum, TreeMap<String,Object> data){
		List<String> keys = new ArrayList<String>(data.keySet());
		ArrayList<Object> temp = new ArrayList<Object>();
		for (int i=0; i<keys.size();i++){
			AppController.getInstance().copy(temp, (createOutput (i, data)).iterator());
			setCells(sheet,temp, (int)rowNum);
			rowNum++;
			temp.clear();
		}
	}

	private ArrayList<Object> createOutput (int i , TreeMap <String,Object> result){
		ArrayList<Object> temp = new ArrayList<Object>();

		String key = new ArrayList<String>(result.keySet()).get(i);
		temp.add(key);
		Object tmp = result.get(key);
		AppController.getInstance().copy(temp, StringUtils.convertExcel(tmp).iterator());
		return temp;
	}
}
